#ifndef IDATACONTAINER_H_
#define IDATACONTAINER_H_


#include <string>
#include <vector>
#include <typeinfo>
#include <boost/any.hpp>
#include "PFileInfo.h"


namespace PComunicator
{



using boost::any_cast;


//! Definicia Container ako datoveho typu  
/*!
 	Container predstavuje datovy typ ktory je tvoreny vektorom tried typu boost::any 
*/
typedef std::vector<boost::any> Container;


//! IDataContainer template rozhranie. 
/*!
 	Rozhranie na definiciu Datoveho kontajnera ktory je pouzity na formatovanie posielanych
	a prijimanych dat ktore posiela PComunicator.
*/
class IDataContainer
{
	public:
		//! Destructor
		/*!
			je nutne prepisat
		*/
		virtual ~IDataContainer(void) {} ;

		//! AddData
		/*!
			Prida data typu T do kolekcie dat ktore sa maju poslat 
			\param theData ake kolvek data typu T
		*/
		template<typename T> void AddData(T theData)
		{
				boost::any aToBeAdded = theData;
				myContainer.push_back(aToBeAdded);
		}

		//! AddCommand
		/*!
			Prida prikaz ktory sa potom posle pomocou PComunicator 
			\param theCommand prikaz ktory sa ma pridat
			\param theOverwrite ak true tak v pripade ze uz nejaky prikaz raz bol pridany tak sa prepise
				   inak sa prikaz zapise len ak zatial nebol pridany ziaden iny prikaz
		*/
		virtual bool AddCommand(std::string theCommand, bool theOverwrite) =0;

		//! Remove
		/*!
			Funkcia sluzi na odobratie data z kolekcie
			\param theData akekolvek data typu T ktore sa ma odstranit z kolekcie
		*/
		template<typename T> bool Remove(T theData)
		{
			for(unsigned int i = 0; i < myContainer.size(); i++)
			{
				if(myContainer[i].type() == typeid(PFileInfo))
				{
					PFileInfo aInput = static_cast<PFileInfo>(theData);
					PFileInfo aFromArray = any_cast<PFileInfo>(myContainer[i]);
					if(aInput.GetName() == aFromArray.GetName())
					{
						myContainer.erase(myContainer.begin()+i);
						return true;
					}
				}
				else
				{
					if(myContainer[i] == theData)
					{
						myContainer.erase(myContainer.begin()+i);
						return true;
					}
				}

			}
			
			return false;
		}


		//! GetContainer
		/*!
			Funkcia sluzi na navratenie kolekcie dat ktore su rovnakeho datoveho typu
			\return navrati kolekciu(vector) daneho datoveho typu obsahujuci vsetky data
					prisluchajuceho typu.
		*/
		template<typename T> std::vector<T> GetContainer()
		{
			std::vector<T> aResult;

			for(unsigned int i=0; i < myContainer.size(); i++)
			{
				if(myContainer[i].type() == typeid(T))
				{
					aResult.push_back(any_cast<T>(myContainer[i]));
				}
			}

			return aResult;
		}

		//! GenerateOutput
		/*!
			Generuje formatovane pole byte, ktore moze byt poslane pomocou PComunicator 
		*/
		virtual bool GenerateOutput(std::vector<byte> &theOutput) = 0;

		//! Parse
		/*!
			Funkcia sluzi na parsovanie formatovaneho pola byte, ktore bolo prijate PComunicator
			\param theInput formatovane pole byte
		*/
		virtual bool Parse(const std::vector<byte> &theInput) = 0;

	protected:
		Container myContainer;
};

}

#endif
